package com.xbn.xbnmall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.xbn.common.constant.AuthServerConstant;
import com.xbn.common.exception.BizCodeEnume;
import com.xbn.common.to.MemberRegistTo;
import com.xbn.common.utils.R;
import com.xbn.common.vo.MemberRespVo;
import com.xbn.xbnmall.auth.feign.MemberFeignService;
import com.xbn.xbnmall.auth.feign.ThirdPartFeignService;
import com.xbn.xbnmall.auth.vo.UserLoginVo;
import com.xbn.xbnmall.auth.vo.UserRegistVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author XBN
 * @date 2020/8/11 15:58
 * @email 78742541@qq.com
 */
@Controller
public class LoginController {
    @Autowired
    private ThirdPartFeignService thirdPartFeignService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping("/login.html")
    public String loginPage(HttpSession session)
    {
        Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER_SESSION_KEY);
        if(attribute==null)
        {
            return "login";
        }
        else {
            return "redirect:http://xbnmall.com";
        }
    }
    @ResponseBody
    @GetMapping("/sms/sendcode")
    public R sendCode(String phone){
        //TODO 接口防刷
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant
                .SMS_CODE_CACHE_PREFIX + phone);
        if(!StringUtils.isEmpty(redisCode)) {
            long saveTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - saveTime < 60 * 1000) {
                //距离上一次发送还未满60s
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(),
                        BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        String  code = ""+(int) (Math.random() * (9999 - 1000 + 1) + 1000);
        //存入当前时间，判断下一次请求时间和现在有没有60s的时间间隔
        String saveCode=code+"_"+System.currentTimeMillis();
        stringRedisTemplate.opsForValue().set(AuthServerConstant
        .SMS_CODE_CACHE_PREFIX+phone,saveCode,15, TimeUnit.MINUTES);
        thirdPartFeignService.sendCode(phone,code);
        return R.ok();
    }

    @PostMapping("regist")
    public String regist(@Valid UserRegistVo userRegistVo, BindingResult result,
                         RedirectAttributes redirectAttributes
                        ){
       if(result.hasErrors())
       {
           //重复键取最新的
            Map<String ,String>  errors= result.getFieldErrors().stream().collect(Collectors.toMap(
                   FieldError::getField,FieldError::getDefaultMessage
           ,(entity1,entity2) -> entity2));

        //实际上是放到session里的FlashAttribute表示数据用一次就会从session中删除掉
           //TODO 分布式下session问题
           redirectAttributes.addFlashAttribute("errors",errors);
           return "redirect:http://auth.xbnmall.com/reg.html";
       }
       //验证码校验
        String code = userRegistVo.getCode();
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant
                .SMS_CODE_CACHE_PREFIX + userRegistVo.getPhone());
     if(!StringUtils.isEmpty(redisCode))
        //if(true)//测试用
        {
        String trueCode=redisCode.split("_")[0];
          if(code.equals(trueCode))
           // if(true) //方便测试
          {
              //验证码通过删除验证码
              stringRedisTemplate.delete(AuthServerConstant
                      .SMS_CODE_CACHE_PREFIX + userRegistVo.getPhone());
              //调用会员服务进行注册
              MemberRegistTo memberRegistTo=new MemberRegistTo();
              BeanUtils.copyProperties(userRegistVo,memberRegistTo);
              R regist = memberFeignService.regist(memberRegistTo);
                if(regist.getCode()==0)
                {
                    //注册成功
                    return "redirect:http://auth.xbnmall.com/login.html";
                }
                else {
                    //注册失败
                    String errorMsg= (String) regist.get("msg");
                    HashMap<String,String> errors=new HashMap<>();
                    errors.put("msg",errorMsg);
                    redirectAttributes.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.xbnmall.com/reg.html";
                }
          }
          else {
              Map<String,String> errors=new HashMap<>();
              errors.put("code","验证码错误");
              //TODO 分布式下session问题
              redirectAttributes.addFlashAttribute("errors",errors);
              return "redirect:http://auth.xbnmall.com/reg.html";
          }
        }
        else {
            Map<String,String> errors=new HashMap<>();
            errors.put("code","验证码超时");
            //TODO 分布式下session问题
            redirectAttributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.xbnmall.com/reg.html";
        }


    }


    @PostMapping("/login")
    public String login(UserLoginVo userLoginVo, RedirectAttributes redirectAttributes, HttpSession
                        session){
        R loginResult = memberFeignService.login(userLoginVo);
        if(loginResult.getCode()==0)
        {
            //登陆成功
            MemberRespVo memberRespVo = loginResult.getData("data", new TypeReference<MemberRespVo>() {
            });
            session.setAttribute(AuthServerConstant.LOGIN_USER_SESSION_KEY
                    ,memberRespVo);

        }
        else {
            //登陆失败
            String msg= (String) loginResult.get("msg");
            HashMap<String,String> errors=new HashMap<>();
            errors.put("msg",msg);
            redirectAttributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.xbnmall.com/login.html";

        }
        return "redirect:http://xbnmall.com";
    }

}
